package com.wenshi.web.netty;

import com.wenshi.common.utils.ChannelMap;
import com.wenshi.system.service.ISysDeviceService;
import com.wenshi.web.netty.codec.ModbusDecoder;
import com.wenshi.web.netty.codec.ModbusEncoder;
import com.wenshi.web.netty.handler.ModbusClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Component
@Data
@Slf4j
public class ModbusClient implements Runnable{
//    String value;
//    int port =502;

    private Channel channel;

    private ChannelFuture channelFuture;

    private EventLoopGroup group;

    private Bootstrap bootstrap;

    int count=0;

    @Autowired
    private ModbusClientHandler modbusClientHandler;
    @Autowired
    private ISysDeviceService sysDeviceService;
    @Autowired
    private com.wenshi.web.service.webService webService;




    ConcurrentHashMap<String,Boolean> shouldReconnect=new ConcurrentHashMap<>();

    // 使用 ConcurrentHashMap 来存储每个host的重试计数
    private ConcurrentHashMap<String, Integer> retryCounts = new ConcurrentHashMap<>();


    @Override
    public void run() {
        group = new NioEventLoopGroup();
        try {
            bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast("modbusDecoder", new ModbusDecoder());
                            ch.pipeline().addLast("modbusEncoder", new ModbusEncoder());
//                            ch.pipeline().addLast("modbusClientHandler", modbusClientHandler);
                        }
                    });
              log.info("Netty客户端已启动。。。。。。。");
            webService.connectDeviceInit();
//            doConnect(value);
        } finally {
//            group.shutdownGracefully();
        }


    }
    public ChannelFuture doConnect(String host,int port) {

        Channel existChannel = ChannelMap.getChannel(host);
        if (existChannel !=null &&existChannel.isActive()){
            log.info("{} 的连接已经存在且激活中", host);
            return channel.newSucceededFuture();
        }
        ChannelFuture future = bootstrap.connect(host, port);
        future.addListener((ChannelFutureListener) futureListener -> {
            if (futureListener.isSuccess()) {
                channel = futureListener.channel(); // 保存连接的Channel
                ChannelMap.getChannelMap().put(host,channel);
                sysDeviceService.updateDeviceByIp(host,Boolean.TRUE);
                shouldReconnect.put(host,true);
                log.info("连接服务器成功: " + host + ":" + port);
                channel.pipeline().addLast("modbusClientHandler", modbusClientHandler);
                retryCounts.put(host, 0);
                // 添加连接关闭监听器
                channel.closeFuture().addListener((ChannelFutureListener) closeFuture -> {
                    if (Boolean.TRUE.equals(shouldReconnect.get(host))){
                        log.info("{}的连接断开，开始重连...",host);
                        // 在连接断开时触发重连操作
                        futureListener.channel().eventLoop().schedule(() -> doConnect(host,port), 5, TimeUnit.SECONDS);
                    }else {
                        log.info("{}的连接断开，不再尝试重连。", host);
                    }
                    ChannelMap.getChannelMap().remove(host);
                });
            }
            else {
                // 从map中获取当前的重试计数
                int currentAttempt = retryCounts.getOrDefault(host, 0);
                retryConnect(host,currentAttempt,futureListener,port);
            }
        });
        return future;
    }

    private void retryConnect(String host, int attempt, ChannelFuture futureListener,int port) {
        if (attempt < 8) {
            log.info("{}连接失败，正在进行第{}次重试...", host, attempt + 1);
            // 更新此host的重试计数
            retryCounts.put(host, attempt + 1);
            // 使用定时任务进行重连
            futureListener.channel().eventLoop().schedule(() -> {
                doConnect(host,port); // 注意这里直接再次调用doConnect
            }, 2, TimeUnit.SECONDS);
            count++;
        } else {
            log.info("{}连接失败，已达到最大重试次数", host);
            sysDeviceService.updateDeviceByIp(host,false);
            // 重置此host的重试计数
            retryCounts.put(host, 0);
        }

    }

    public void discConnect(String host){
        //通过ip地址断开指定连接
        Channel closeChannel = ChannelMap.getChannel(host);
        if (closeChannel!=null){
            // 更新标志位，表明连接关闭后不应再自动重连
            shouldReconnect.put(host, false);
            closeChannel.close().addListener(future -> {
                if (future.isSuccess()){
                    log.info("ip地址为：{}的channel关闭成功",host);
                }else {
                    log.info("ip地址为：{}的channel关闭失败",host);
                }
            });
        }
    }
}
